# -----------
# User Instructions
#
# Define a function smooth that takes a path as its input
# (with optional parameters for weight_data, weight_smooth)
# and returns a smooth path.
#
# Smoothing should be implemented by iteratively updating
# each enry in newpath until some desired level of accuracy
# is reached. The update should be done according to the
# gradient descent equations given in the previous video:
#
# Note that you do not need to use the tolerance parameter
# shown in the video. 
#
# If your function isn't submitting it is possible that the
# runtime is too long. Try sacrificing accuracy for speed.


from math import *

path=[[0, 0], #Don't modify path inside your function.
      [0, 1],
      [0, 2],
      [1, 2],
      [2, 2],
      [3, 2],
      [4, 2],
      [4, 3],
      [4, 4]]

# ------------------------------------------------
# smooth coordinates
#

def smooth(path, weight_data = 0, weight_smooth = 0.5):

    newpath = [[0 for row in range(len(path[0]))] for col in range(len(path))]
    for i in range(len(path)):
        for j in range(len(path[0])):
            newpath[i][j] = path[i][j] # This makes a deep copy of path into newpath

    error = 1
    while error > 0.000001:
        error = 0
        for i in range(1, len(path)-1):
            for j in range(len(path[0])):
                old = newpath[i][j]
                newpath[i][j] += weight_data * (path[i][j] - newpath[i][j])
                newpath[i][j] += weight_smooth * (newpath[i+1][j] + newpath[i-1][j] - 2 * newpath[i][j])
                error += abs(old - newpath[i][j])

    return newpath #Leave this line for the grader!

newpath = smooth(path) # feel free to leave this and the following lines if you want to print.

for i in range(len(path)):
  print '['+ ', '.join('%.3f'%x for x in path[i]) +'] -> ['+ ', '.join('%.3f'%x for x in newpath[i]) +']'

# thank you - EnTerr - for posting this on our discussion forum
raw_input()